package com.asambleacristiana.repository.dao.impl;

import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import org.apache.commons.lang3.StringUtils;

import com.asambleacristiana.domain.CuentaEnum;
import com.asambleacristiana.domain.Movimiento;
import com.asambleacristiana.domain.TipoOperacionEnum;
import com.asambleacristiana.domain.Zona;
import com.asambleacristiana.repository.dao.AbstractDAO;
import com.asambleacristiana.repository.dao.MovimientoDAO;

/**
 * @author PBalegno
 * */
public class MovimientoDAOImpl extends AbstractDAO<Movimiento> implements MovimientoDAO {

	private EntityManagerFactory entityManagerFactory = null;

	public MovimientoDAOImpl(EntityManagerFactory entityManagerFactory) {
		super(entityManagerFactory);
		this.entityManagerFactory = entityManagerFactory;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Movimiento> find(Integer zona, Date fechaDesde, Date fechaHasta) {
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		try {
			String sql = "SELECT m FROM Movimiento m WHERE (m.fecha >= :fechaDesde AND m.fecha <= :fechaHasta) AND m.zona.codigo=:zona AND m.fechaBaja = null ORDER by m.fecha DESC";
			Query query = entityManager.createQuery(sql);
			query.setParameter("zona", zona);
			query.setParameter("fechaDesde", fechaDesde);
			query.setParameter("fechaHasta", fechaHasta);
			return (List<Movimiento>) query.getResultList();
		} finally {
			entityManager.close();
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Movimiento> find(Date fechaDesde, Date fechaHasta, List<Zona> zonas) {
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		try {
			String sql = "SELECT m FROM Movimiento m WHERE (m.fecha >= :fechaDesde AND m.fecha <= :fechaHasta) AND m.fechaBaja = null AND m.zona IN (:zona) ORDER by m.zona.nombre, m.fecha DESC";
			Query query = entityManager.createQuery(sql);
			query.setParameter("zona", zonas);
			query.setParameter("fechaDesde", fechaDesde);
			query.setParameter("fechaHasta", fechaHasta);
			return (List<Movimiento>) query.getResultList();
		} finally {
			entityManager.close();
		}
	}
	
	public Date getMinFecha(List<Zona> zonas) {
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		try {
			String sql = "SELECT min(m.fecha) FROM Movimiento m WHERE m.fechaBaja = null AND m.zona IN (:zonas)";
			Query query = entityManager.createQuery(sql);
			query.setParameter("zonas", zonas);
			return (Date)query.getSingleResult();
		} finally {
			entityManager.close();
		}
		
	}
	
	@Override
	public Date getMinFecha(Integer zona) {
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		try {
			String sql = "SELECT min(m.fecha) FROM Movimiento m WHERE m.zona.codigo=:zona AND m.fechaBaja = null";
			Query query = entityManager.createQuery(sql);
			query.setParameter("zona", zona);
			return (Date)query.getSingleResult();
		} finally {
			entityManager.close();
		}
	}

	@Override
	public boolean find(Movimiento m) {
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		try {
			String sql = "SELECT m FROM Movimiento m " + "WHERE m.desde.codigo=:desde " + "AND m.hasta.codigo=:hasta " + "AND m.fecha=:fecha "
					+ "AND m.importe=:importe " + "AND m.tipoOperacion.codigo=:tipoOperacion " + "AND m.zona.codigo=:zona ";

			if (!StringUtils.isBlank(m.getNroCuit())) {
				sql += "AND m.nroCuit = :nroCuit ";
			}
			if (!StringUtils.isBlank(m.getNroFactura())) {
				sql += "AND m.nroFactura = :nroFactura ";
				sql += "AND m.tipoFactura = :tipoFactura ";
			}

			sql += "AND m.fechaBaja = null";

			Query query = entityManager.createQuery(sql);
			query.setParameter("desde", m.getDesde().getCodigo());
			query.setParameter("hasta", m.getHasta().getCodigo());
			query.setParameter("fecha", m.getFecha());
			query.setParameter("importe", m.getImporte());
			query.setParameter("tipoOperacion", m.getTipoOperacion().getCodigo());
			query.setParameter("zona", m.getZona().getCodigo());

			if (!StringUtils.isBlank(m.getNroCuit())) {
				query.setParameter("nroCuit", m.getNroCuit());
			}
			if (!StringUtils.isBlank(m.getNroFactura())) {
				query.setParameter("nroFactura", m.getNroFactura());
				query.setParameter("tipoFactura", m.getTipoFactura());

			}

			return (Movimiento)query.getSingleResult() != null;
		} catch (NoResultException e) {
			return false;
		} finally {
			entityManager.close();
		}
	}

	@Override
	public void eliminarMovimiento(Long codMovimiento, String usuario) {
		Movimiento mov = findById(codMovimiento);
		mov.setFechaBaja(new Date());
		mov.setUsuBaja(usuario);
		persist(mov);
	}

	@Override
	public Double findIngresosByFilial(Integer zona, Date fechaDesde, Date fechaHasta) {
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		try {
			String sql = "SELECT SUM(m.importe) FROM Movimiento m " + " WHERE (m.fecha >= :fechaDesde AND m.fecha <= :fechaHasta) "
					+ " AND m.zona.codigo=:zona " + " AND m.fechaBaja = null " + " AND m.tipoOperacion.codigo = :tipoOperacion "
					+ " AND m.desde.codigo <> :cuenta ";
			Query query = entityManager.createQuery(sql);
			query.setParameter("zona", zona);
			query.setParameter("fechaDesde", fechaDesde);
			query.setParameter("fechaHasta", fechaHasta);
			query.setParameter("tipoOperacion", TipoOperacionEnum.ingreso.getCodigo());
			query.setParameter("cuenta", CuentaEnum.transferenciasDeFiliales.getCodigo());
			return (Double) query.getSingleResult();
		} finally {
			entityManager.close();
		}
	}

}
